str = "I will set register 1 to 9 [setv(1,9)] \\%1 is %1 [add(%1,add(1,add(1)))] and here is the sum to add(%1,add(10,add(5,setv(1,1)setv(2,0)\\%1\\%2))) : [add(%1,[add(10,[add(5,[setv(1,1)][setv(2,0)]%1%2))]])] [x(date)] [eval(self.to_s)]"

require '/home/ppibburr/muide1/libs/utilities/main/mucode'
$procs = {}
$procs["eval"]=proc do |parent,*args|
  eval(args[0]).to_s
end
$procs["x"]=proc do |parent,*args|
  eval("%x[#{args[0]}]")
end
# $procs["add_"]=proc do |*args|
# 
# end
# $procs["add_"]=proc do |*args|
# 
# end
$procs["setv"]=proc do |parent_function,*args|
p args
p '------'
  parent_function.registers[args[0].to_i]=args[1]
""
end
$procs["add"]=proc do |parent,*args|
 ct = 0
 args.each {|a|
   ct = ct + a.to_i
 }
 return ct.to_s
end
class Function
  attr_accessor :current_param,:params,:registers,:parent
  def initialize ins,function,procs
    @procs = procs
    @params = [""]
    @function = function
    @registers=[]
# p function
    @current_param = 0
#     if ins.functions.length > 1
     begin
      @parent = ins.open_functions[ins.open_functions.length-1]
    rescue
      @parent=ins
    end
@parent = ins if @parent == nil
# p ins.open_functions[ins.open_functions.length-1]
# p ins.functions
p @parent.class
  end
  def evaluate
    @procs[@function].call(@parent,*@params)
  end
  def next_param
    @params << ""
    @current_param = @params.length-1
  end
end
class Eval
 attr_accessor :value,:functions,:registers,:open_functions
  def initialize str
    @tokens = Tokenizer.tokenize(str)
    @value = ""
    @functions = []
    @function=0
    @open_functions = []
    @registers=[]
  end
  def evaluate 
    @tokens.each {|t|
      case t[1]
         when :substitution
           i = t[0][1..t[0].length]
           if i =~ /([0-9]+)/
             if @function > 0
              if @last_function.params.length > 1
p @last_function.registers
p $1
                @last_function.params[@last_function.params.length-1] = @last_function.params.last + @last_function.registers[$1.to_i]
p @last_function.params[@last_function.params.length-1]
              else
                @last_function.params[0] = @last_function.params[0]+@last_function.parent.registers[$1.to_i]
              end
             else
              @value = @value + @registers[$1.to_i]
p "#{@value}===="
             end
           end
         when :eval_start

         when :eval_end
           
         when :function_start
           @functions << Function::new(self,t[0][0..t[0].length-2],$procs)
           @open_functions << @functions.last
           @last_function = @functions.last
           @function = @function + 1
         when :function_param_sep
           @last_function.next_param
         when :function_end
           @function = @function - 1
           value = @last_function.evaluate
#            p @last_function.params
           @open_functions.delete(@last_function)
#            p value
          if @open_functions!=[]
             @last_function = @open_functions.last
             @last_function.params[@last_function.current_param] = @last_function.params[@last_function.current_param]+value
#              p @last_function.current_para
           else
             @value=@value+value
           end
      else
        if @function > 0 
          @last_function.params[@last_function.current_param] = @last_function.params[@last_function.current_param]+t[0]
#           p @last_function.current_param+"00000"
        else
          @value = @value+t[0]
        end
      end
    }
  end
end

e = Eval::new(str)
e.evaluate
p e.value
